import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';

enum HZNetworkFetchMethod {
  get,
  post,
}

class HZNetwork {
  factory HZNetwork() => _instance;
  static final HZNetwork _instance = HZNetwork._internal();
  Dio _dio = Dio();

  HZNetwork._internal() {
    _dio.options
      ..baseUrl = 'http://47.105.182.54:18096'
      ..connectTimeout = 30000
      ..receiveTimeout = 30000
      ..headers = {
      "X-JGT-TOKEN": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuZXRfdHlwZSI6IldJRkkiLCJwaG9uZV9icmFuZCI6IkFwcGxlIiwidXVpZCI6IjcwOEU1NEJELTBBNjUtNDc3Ni1CRkU2LTc5QjAyOEYxMTA0MCIsInZlcnNpb24iOiIxLjAuMCIsIm1xdHRfdG9rZW4iOiIiLCJjaGFubmVsIjoiaW9zIiwidGltZXN0YW1wIjoxNjIzMzkxNDUxLCJlbnRlcnByaXNlX2lkIjoiMmUyM2RkZmItM2EyOS00ZjM4LWI0OWUtZjJiNmRjMjk2NDY4IiwidXNlcl90eXBlIjoiNDAiLCJzb3VyY2UiOiJBcHAgU3RvcmUiLCJvcyI6ImlPUyIsImRldmljZV90eXBlIjoiaVBob25lIiwic2NyZWVuX2hlaWdodCI6ODk2LCJkZXZpY2VfaWQiOiJCQUQxQUVGRC1GM0M1LTQxMzItQjU4RC0zQ0IxMTVEQTNDQzQiLCJvc192ZXJzaW9uIjoiMTQuMCIsInNjcmVlbl93aWR0aCI6NDE0LCJwYXJrX2lkIjoiUjM3MTEwMTIwMjAwNDExMTExMTEiLCJwaG9uZV9tb2RlbCI6ImlQaG9uZSBYUiJ9.MUKFy1uQqDAGBuGsx9DN-Ey8Fj01Sdhh4KM3exkZLALb--99J3Rd-Ok2o-iEyI48vQvAZe-bIj0pMVc44kbWog"
      }
      ..contentType = Headers.jsonContentType;

    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      client.findProxy = (uri) {
        return "PROXY 192.168.3.56:8888";
      };
    };
    _dio.interceptors.add(LogInterceptor(responseBody: true)); //开启请求日志
    // _dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
    //   // 如果你想完成请求并返回一些自定义数据，你可以resolve一个Response对象 `handler.resolve(response)`。
    //   // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义response.
    //   //
    //   // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,如`handler.reject(error)`，
    //   // 这样请求将被中止并触发异常，上层catchError会被调用。
    //   //
    //   print(
    //       '===>🚀🚀🚀发起请求[${options.method}] => PATH: ${options.path} \n 参数${options.data}');
    //
    //   return handler.next(options); //continue
    // }, onResponse: (response, handler) {
    //   // Do something with response data
    //   // 如果你想终止请求并触发一个错误,你可以 reject 一个`DioError`对象,如`handler.reject(error)`，
    //   // 这样请求将被中止并触发异常，上层catchError会被调用。
    //   print('===>🎉🎉🎉收到响应:$response');
    //   print('===>✅✅✅✅收到响应data:${response.data}');
    //
    //   return handler.next(response); // continue
    // }, onError: (DioError err, handler) {
    //   // 如果你想完成请求并返回一些自定义数据，可以resolve 一个`Response`,如`handler.resolve(response)`。
    //   // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义response.
    //   print(
    //       '===>❌❌❌❌发生错误ERROR[${err.response?.statusCode}] => PATH: ${err.response.realUri}');
    //   return handler.next(err); //continue
    // }));
  }

  ///
  /// 配置拦截器
  /// 每个 Dio 实例都可以添加任意多个拦截器，他们组成一个队列，拦截器队列的执行顺序是FIFO。
  /// 通过拦截器你可以在请求之前、响应之后和发生异常时(但还没有被 then 或 catchError处理)做一些统一的预处理操作。
  /// [interceptors] List 可自定义拦截器(extends Interceptor)
  ///
  static configInterceptors(List<Interceptor> interceptors) {
    assert(interceptors.length != 0, "拦截器不可为空");
    _instance._dio.interceptors.addAll(interceptors);
  }

  /// 配置网络请求框架头部信息
  /// [headers]  类型：map
  ///
  static configHeaders(Map<String, dynamic> headers) {
    _instance._dio.options.headers.addAll(headers);
  }

  // static FormData getFormRequestData(Map data) {
  //   assert(data !=null,"data 不能为空");
  //   assert(data is Map ,"data 类型不匹配，需要Map类型");
  //   var files = data['files'];
  //   assert (files is Map, "key:files,所对应的value应该为Map");
  //   FormData formData = FormData();
  //   formData.fields.addAll(iterable)
  //   Iterable<MapEntry> multipartFiles= (files as List).map((file) => MultipartFile.fromFileSync(file["file"],filename: file["name"]));
  //   formData.files.addAll(multipartFiles);
  //   return formData;
  // }
  ///
  ///  发起网络请求
  ///  [HZNetworkConfig] config
  ///
  static Future<Response<T>> request<T>(HZNetworkConfig config) {
    String requestMethod = 'GET';
    switch (config.method) {
      case HZNetworkFetchMethod.post:
        requestMethod = 'POST';
        break;
    }
    return _instance._dio.request(
      config.url,
      data: config.data,
      queryParameters:
          config.method == HZNetworkFetchMethod.get ? config.data : null,
      options: config.options,
    );
  }
}

///
/// HZNetworkConfig 单次请求信息配置
/// [HZNetworkFetchMethod] 请求方式
/// [data]  请求参数 Map or FormData ..
/// [url] 请求path
/// [options] Options类描述了每一个Http请求的配置信息，每一次请求都可以单独配置，单次请求的Options中的配置信息可以覆盖BaseOptions中的配置
///
class HZNetworkConfig {
  HZNetworkFetchMethod method;
  dynamic data;
  String url;
  Options options;

  HZNetworkConfig(this.method, this.url, {this.data, this.options});
}
